package com.tools.middle.elasticsearch;

import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery;
import co.elastic.clients.elasticsearch.core.search.HighlightField;
import co.elastic.clients.json.JsonData;
import com.tools.common.container.OwnPairs;
import com.tools.common.object.Note;
import com.tools.common.thread.Timeunit;

import java.util.Map;

/**
 * ElasticSearch Range 范围查询的构建实例
 * 继承父类的方法在多条件查询时不起作用（除了分词器）
 * */
@Note("ElasticSearch Range 范围查询的构建实例。" +
        "继承父类的方法在多条件查询时不起作用（除了分词器）")
public final class RangeSearch extends Search {

    @Note("格式化字符串")
    private String formatter = "yyyy-MM-dd HH:mm:ss";

    @Note("查询范围的字段名称")
    private String field;

    @Note("开始大于的临界值")
    private Object gt;

    @Note("开始大于等于的临界值")
    private Object gte;

    @Note("开始小于的临界值")
    private Object lt;

    @Note("开始小于等于的临界值")
    private Object lte;

    /* ***********************************************************************************
     *
     *         构造器
     *
     * **********************************************************************************
     * */

    public RangeSearch(String field) {
        this.setField(field);
    }

    public static RangeSearch of(String field) {
        return new RangeSearch(field);
    }

    /* ***********************************************************************************
     *
     *         Getter / Setter
     *
     * **********************************************************************************
     * */

    public String getField() {
        return field;
    }

    public void setField(String field) {
        if(field == null || field.isEmpty()) throw new NullPointerException("字段名称为空");
        this.field = field;
    }

    public String getFormatter() {
        return formatter;
    }

    public void setFormatter(String formatter) {
        if(formatter == null || formatter.isEmpty()) return;
        this.formatter = formatter;
    }

    public Object getGt() {
        return gt;
    }

    public void setGt(Object gt) {
        this.gt = gt;
    }

    public Object getGte() {
        return gte;
    }

    public void setGte(Object gte) {
        this.gte = gte;
    }

    public Object getLt() {
        return lt;
    }

    public void setLt(Object lt) {
        this.lt = lt;
    }

    public Object getLte() {
        return lte;
    }

    public void setLte(Object lte) {
        this.lte = lte;
    }

    /* ***********************************************************************************
     *
     *         链式方法
     *
     * **********************************************************************************
     * */

    public RangeSearch formatter(String formatter) {
        this.setFormatter(formatter);
        return this;
    }

    public RangeSearch field(String field) {
        this.setField(field);
        return this;
    }

    public RangeSearch gte(Object gte) {
        this.setGte(gte);
        return this;
    }

    public RangeSearch gt(Object gt) {
        this.setGt(gt);
        return this;
    }

    public RangeSearch lte(Object lte) {
        this.setLte(lte);
        return this;
    }

    public RangeSearch lt(Object lt) {
        this.setLt(lt);
        return this;
    }

    @Override
    public RangeSearch indicesNames(String indicesName) {
        super.indicesNames(indicesName);
        return this;
    }

    @Override
    public RangeSearch indicesNames(String[] indicesNames) {
        super.indicesNames(indicesNames);
        return this;
    }

    @Override
    public RangeSearch indicesNames(Iterable<String> indicesNames) {
        super.indicesNames(indicesNames);
        return this;
    }

    @Override
    public RangeSearch timeout(String timeout) {
        super.timeout(timeout);
        return this;
    }

    @Override
    public RangeSearch timeout(int timeout, Timeunit timeunit) {
        super.timeout(timeout, timeunit);
        return this;
    }

    @Override
    public RangeSearch from(int from) {
        super.from(from);
        return this;
    }

    @Override
    public RangeSearch size(int size) {
        super.size(size);
        return this;
    }

    @Override
    public RangeSearch analyzer(String analyzer) {
        super.analyzer(analyzer);
        return this;
    }

    @Override
    public RangeSearch sorts(String field, SortOrder order) {
        super.sorts(field, order);
        return this;
    }

    @Override
    public RangeSearch sorts(Map<String, SortOrder> fieldAndOrders) {
        super.sorts(fieldAndOrders);
        return this;
    }

    @Override
    public RangeSearch sorts(OwnPairs<String, SortOrder> fieldAndOrders) {
        super.sorts(fieldAndOrders);
        return this;
    }

    @Override
    public RangeSearch includes(String includeField) {
        super.includes(includeField);
        return this;
    }

    @Override
    public RangeSearch includes(String[] includeFields) {
        super.includes(includeFields);
        return this;
    }

    @Override
    public RangeSearch includes(Iterable<String> includeFields) {
        super.includes(includeFields);
        return this;
    }

    @Override
    public RangeSearch excludes(String excludeField) {
        super.excludes(excludeField);
        return this;
    }

    @Override
    public RangeSearch excludes(String[] excludeFields) {
        super.excludes(excludeFields);
        return this;
    }

    @Override
    public RangeSearch excludes(Iterable<String> excludeFields) {
        super.excludes(excludeFields);
        return this;
    }

    @Override
    public RangeSearch aggregations(String field, Aggregation agg) {
        super.aggregations(field, agg);
        return this;
    }

    @Override
    public RangeSearch aggregations(Map<String, Aggregation> aggregations) {
        super.aggregations(aggregations);
        return this;
    }

    @Override
    public RangeSearch aggregations(OwnPairs<String, Aggregation> aggregations) {
        super.aggregations(aggregations);
        return this;
    }

    @Override
    public RangeSearch highlights(String field, HighlightField highlight) {
        super.highlights(field, highlight);
        return this;
    }

    @Override
    public RangeSearch highlights(Map<String, HighlightField> highlights) {
        super.highlights(highlights);
        return this;
    }

    @Override
    public RangeSearch highlights(OwnPairs<String, HighlightField> highlights) {
        super.highlights(highlights);
        return this;
    }

    /* ***********************************************************************************
     *
     *         自定义方法
     *
     * **********************************************************************************
     * */

    @Note("设置要检索的内容到查询器里，并清空容器")
    public RangeQuery.Builder putRange(RangeQuery.Builder builder) {
        private_checkData();
        if (gte != null) builder.gte(JsonData.of(gte));
        if (gt != null) builder.gt(JsonData.of(gt));
        if (lte != null) builder.lte(JsonData.of(lte));
        if (lt != null) builder.lt(JsonData.of(lt));
        return builder.format(formatter).field(field);
    }

    @Override
    public RangeSearch addIndicesName(String indicesName) {
        super.addIndicesName(indicesName);
        return this;
    }

    @Override
    public RangeSearch addIndicesNames(String... indicesNames) {
        super.addIndicesNames(indicesNames);
        return this;
    }

    @Override
    public RangeSearch addIndicesNames(Iterable<String> indicesNames) {
        super.addIndicesNames(indicesNames);
        return this;
    }

    @Override
    public RangeSearch modifyIndicesName(int index, String indicesName) {
        super.modifyIndicesName(index, indicesName);
        return this;
    }

    @Override
    public RangeSearch removeIndicesName(String indicesName) {
        super.removeIndicesName(indicesName);
        return this;
    }

    @Override
    public RangeSearch removeIndicesName(int index) {
        super.removeIndicesName(index);
        return this;
    }

    @Override
    public RangeSearch removeIndicesNames(String... indicesNames) {
        super.removeIndicesNames(indicesNames);
        return this;
    }

    @Override
    public RangeSearch removeIndicesNames(Iterable<String> indicesNames) {
        super.removeIndicesNames(indicesNames);
        return this;
    }

    @Override
    public RangeSearch addSort(String field, SortOrder order) {
        super.addSort(field, order);
        return this;
    }

    @Override
    public RangeSearch addSorts(Map<String, SortOrder> fieldAndOrders) {
        super.addSorts(fieldAndOrders);
        return this;
    }

    @Override
    public RangeSearch addSorts(OwnPairs<String, SortOrder> fieldAndOrders) {
        super.addSorts(fieldAndOrders);
        return this;
    }

    @Override
    public RangeSearch modifySort(int index, String field, SortOrder order) {
        super.modifySort(index, field, order);
        return this;
    }

    @Override
    public RangeSearch clearSorts() {
        super.clearSorts();
        return this;
    }

    @Override
    public RangeSearch removeSort(String field, SortOrder order) {
        super.removeSort(field, order);
        return this;
    }

    @Override
    public RangeSearch removeSort(int index) {
        super.removeSort(index);
        return this;
    }

    @Override
    public RangeSearch removeSorts(Map<String, SortOrder> fieldAndOrders) {
        super.removeSorts(fieldAndOrders);
        return this;
    }

    @Override
    public RangeSearch removeSorts(OwnPairs<String, SortOrder> fieldAndOrders) {
        super.removeSorts(fieldAndOrders);
        return this;
    }

    @Override
    public RangeSearch addInclude(String field) {
        super.addInclude(field);
        return this;
    }

    @Override
    public RangeSearch addIncludes(String... fields) {
        super.addIncludes(fields);
        return this;
    }

    @Override
    public RangeSearch addIncludes(Iterable<String> fields) {
        super.addIncludes(fields);
        return this;
    }

    @Override
    public RangeSearch modifyInclude(int index, String field) {
        super.modifyInclude(index, field);
        return this;
    }

    @Override
    public RangeSearch clearIncludes() {
        super.clearIncludes();
        return this;
    }

    @Override
    public RangeSearch removeInclude(String field) {
        super.removeInclude(field);
        return this;
    }

    @Override
    public RangeSearch removeInclude(int index) {
        super.removeInclude(index);
        return this;
    }

    @Override
    public RangeSearch removeIncludes(String... fields) {
        super.removeIncludes(fields);
        return this;
    }

    @Override
    public RangeSearch removeIncludes(Iterable<String> fields) {
        super.removeIncludes(fields);
        return this;
    }

    @Override
    public RangeSearch addExclude(String field) {
        super.addExclude(field);
        return this;
    }

    @Override
    public RangeSearch addExcludes(String... fields) {
        super.addExcludes(fields);
        return this;
    }

    @Override
    public RangeSearch addExcludes(Iterable<String> fields) {
        super.addExcludes(fields);
        return this;
    }

    @Override
    public RangeSearch modifyExclude(int index, String field) {
        super.modifyExclude(index, field);
        return this;
    }

    @Override
    public RangeSearch clearExcludes() {
        super.clearExcludes();
        return this;
    }

    @Override
    public RangeSearch removeExclude(String field) {
        super.removeExclude(field);
        return this;
    }

    @Override
    public RangeSearch removeExclude(int index) {
        super.removeExclude(index);
        return this;
    }

    @Override
    public RangeSearch removeExcludes(String... fields) {
        super.removeExcludes(fields);
        return this;
    }

    @Override
    public RangeSearch removeExcludes(Iterable<String> fields) {
        super.removeExcludes(fields);
        return this;
    }

    @Override
    public RangeSearch addAgg(String field, Aggregation agg) {
        super.addAgg(field, agg);
        return this;
    }

    @Override
    public RangeSearch addAggs(Map<String, Aggregation> aggs) {
        super.addAggs(aggs);
        return this;
    }

    @Override
    public RangeSearch addAggs(OwnPairs<String, Aggregation> aggs) {
        super.addAggs(aggs);
        return this;
    }

    @Override
    public RangeSearch clearAggs() {
        super.clearAggs();
        return this;
    }

    @Override
    public RangeSearch removeAgg(String field) {
        super.removeAgg(field);
        return this;
    }

    @Override
    public RangeSearch removeAgg(String... fields) {
        super.removeAgg(fields);
        return this;
    }

    @Override
    public RangeSearch removeAgg(Iterable<String> fields) {
        super.removeAgg(fields);
        return this;
    }

    @Override
    public RangeSearch addHighlight(String field, HighlightField highlight) {
        super.addHighlight(field, highlight);
        return this;
    }

    @Override
    public RangeSearch addHighlights(Map<String, HighlightField> highlights) {
        super.addHighlights(highlights);
        return this;
    }

    @Override
    public RangeSearch addHighlights(OwnPairs<String, HighlightField> highlights) {
        super.addHighlights(highlights);
        return this;
    }

    @Override
    public RangeSearch clearHighlight() {
        super.clearHighlight();
        return this;
    }

    @Override
    public RangeSearch removeHighlight(String field) {
        super.removeHighlight(field);
        return this;
    }

    @Override
    public RangeSearch removeHighlights(String... fields) {
        super.removeHighlights(fields);
        return this;
    }

    @Override
    public RangeSearch removeHighlights(Iterable<String> fields) {
        super.removeHighlights(fields);
        return this;
    }

    /* ***********************************************************************************
     *
     *         私有逻辑
     *
     * **********************************************************************************
     * */

    @Note("校验是否存在必须的数据")
    private void private_checkData() {
        if(gte == null && gt == null && lte == null && lt == null) throw new IllegalArgumentException("你必须指定一个范围才能使用该实例");
    }
}
